﻿using System;
using System.Windows;

namespace SStuff.FlowControls
{
    /// <summary>
    /// FlowItemsControl based on a IFlowLayout3DAlgorithm
    /// </summary>
    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(FlowItem3D))]
    public class FlowItemsControl3D : FlowItemsControlBase
    {
        /// <summary>
        /// Create an instance of FlowItemsControl3D
        /// </summary>
        public FlowItemsControl3D()
        {
            DefaultStyleKey = typeof(FlowItemsControl3D);
        }

        IFlowPanel3D _panel;


        /// <summary>
        /// Get the normalized offset [-1 - +1] for a given mouse position
        /// </summary>
        /// <param name="mousePosition"></param>
        /// <returns></returns>
        protected override double GetNormalizedGestureOffset(Point mousePosition)
        {
            var intermediate = LayoutAlgorithm.GetNormalizedOffsetAtPoint(mousePosition);
            //var consideredItems = Math.Min(Items.Count, LayoutAlgorithm.GetMaxDisplayedItems());
            return intermediate;
        }

        /// <summary>
        /// Get the number of items to consider for layouting (used for virtualization purpose)
        /// </summary>
        /// <returns></returns>
        protected override int GetConsideredItems()
        {
            return Math.Min(Items.Count, LayoutAlgorithm.GetMaxDisplayedItems());
        }

        /// <summary>
        /// Get a value indicating if gestures should be handled
        /// </summary>
        protected override bool HandleGestures
        {
            get { return LayoutAlgorithm != null && LayoutAlgorithm.SupportsGestures; }
        }

        /// <summary>
        /// Handles changes in the collection of items
        /// </summary>
        /// <param name="e"></param>
        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            if (_panel != null)
                _panel.ItemCount = Items.Count;

            
        }


        /// <summary>
        /// Style of the Item containers
        /// </summary>
        public Style ItemContainerStyle
        {
            get { return (Style)GetValue(ItemContainerStyleProperty); }
            set { SetValue(ItemContainerStyleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemContainerStyle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemContainerStyleProperty =
            DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(FlowItemsControl3D), new PropertyMetadata(null));

        /// <summary>
        /// Creates or identifies the element that is used to display the given item.
        /// </summary>
        /// <returns>
        /// The element that is used to display the given item.
        /// </returns>
        protected override DependencyObject GetContainerForItemOverride()
        {
            
            var container = new FlowItem3D();
            if (ItemContainerStyle != null)
                container.Style = ItemContainerStyle;
            return container;
        }

        /// <summary>
        /// Determines if the specified item is (or is eligible to be) its own container.
        /// </summary>
        /// <returns>
        /// true if the item is (or is eligible to be) its own container; otherwise, false.
        /// </returns>
        /// <param name="item">The item to check.</param>
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is FlowItem3D;
        }



        /// <summary>
        /// Notify the underlaying panel of the layout offset change
        /// </summary>
        protected override void OnLayoutOffsetChanged()
        {
            base.OnLayoutOffsetChanged();
            if (_panel != null)
            {
                _panel.LayoutOffset = LayoutOffset;
            }
        }

        /// <summary>
        /// Notify the underlaying panel of the cyclic mode change
        /// </summary>
        protected override void OnCyclicModeChanged()
        {
            base.OnCyclicModeChanged();
            if (_panel != null)
            {
                _panel.CyclicMode = CyclicMode;
            }
        }

        /// <summary>
        /// Connect the FlowItemsControl with its panel
        /// </summary>
        protected override void OnVirtualHostChanged()
        {
            base.OnVirtualHostChanged();
            _panel = VirtualHost as IFlowPanel3D;
            if (_panel != null)
            {
                _panel.LayoutAlgorithm = LayoutAlgorithm;
                _panel.LayoutOffset = LayoutOffset;

                _panel.ItemCount = Items.Count;

                _panel.CyclicMode = CyclicMode;
            }
        }

        /// <summary>
        /// Notify the underlaying panel of a layout algorithm change
        /// </summary>
        private void OnLayoutAlgorithmChanged()
        {
            if (_panel != null)
            {
                _panel.LayoutAlgorithm = LayoutAlgorithm;
            }
        }



        /// <summary>
        /// Get or set the associated layout algorithm
        /// </summary>
        public IFlowLayout3DAlgorithm LayoutAlgorithm
        {
            get { return (IFlowLayout3DAlgorithm)GetValue(LayoutAlgorithmProperty); }
            set { SetValue(LayoutAlgorithmProperty, value); }
        }

        /// <summary>
        /// DependencyProperty for LayoutAlgorithm
        /// </summary>
        public static readonly DependencyProperty LayoutAlgorithmProperty =
            DependencyProperty.Register("LayoutAlgorithm", typeof(IFlowLayout3DAlgorithm), typeof(FlowItemsControl3D), new PropertyMetadata(new CoverFlow3D(),
                (s, a) => ((FlowItemsControl3D) s).OnLayoutAlgorithmChanged()));


    }
}
